#include "mrunner.h"

NodeMRunner::NodeMRunner(Node *parent, NodeMRunnerParam params) :
    Node(parent)
{
    port_chain_in = new ChannelLoadFabricReceiver(this);
    port_chain_out = new ChannelLoadFabricSender(this);
    port_message_in = new ChannelLoadFabricReceiver(this);
    port_message_out = new ChannelLoadFabricSender(this);
    port_halt = new PortOut<bool>(this);
    reg_pid_filter = 0;
    for(int temp_885062064=0; temp_885062064<params.peer_ids.size(); temp_885062064+=1)
    {
        int pid = params.peer_ids[temp_885062064];
        reg_pid_filter |= (1)<<(pid);
    }
}

NodeTaskList NodeMRunner::tasks() const
{
    NodeTaskList list;
    list.append(static_cast<NodeTask>(&NodeMRunner::task_process_passing));
    list.append(static_cast<NodeTask>(&NodeMRunner::task_halt_detection));
    return list;
}

void NodeMRunner::task_process_passing()
{
    if(!(port_chain_in->Bus->is_any_empty()))
    {
        reg_peer_id = port_chain_in->Bus->pid->head();
        if(((reg_peer_id)&(reg_pid_filter))>(0))
        {
            if(!(port_message_out->Bus->is_any_full()))
            {
                port_message_out->Bus->put_bypass(port_chain_in->Bus);
            }
        }
        else
        {
            if(!(port_chain_out->Bus->is_any_full()))
            {
                port_chain_out->Bus->put_bypass(port_chain_in->Bus);
            }
        }
    }
    else
    {
        if(!(port_message_in->Bus->is_any_empty()))
        {
            reg_peer_id = port_message_in->Bus->pid->head();
            if(((reg_peer_id)&(reg_pid_filter))>(0))
            {
                if(!(port_message_out->Bus->is_any_full()))
                {
                    port_message_out->Bus->put_bypass(port_message_in->Bus);
                }
            }
            else
            {
                if(!(port_chain_out->Bus->is_any_full()))
                {
                    port_chain_out->Bus->put_bypass(port_message_in->Bus);
                }
            }
        }
    }
}

void NodeMRunner::task_halt_detection()
{
    port_halt->put((port_message_in->Bus->is_any_empty())&&(port_chain_in->Bus->is_any_empty()));
}